package com.ziyucoding.springboot.labs.redislike.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ziyucoding.springboot.labs.redislike.common.Constant;
import com.ziyucoding.springboot.labs.redislike.domain.UserLikes;
import com.ziyucoding.springboot.labs.redislike.domain.ViewItem;
import com.ziyucoding.springboot.labs.redislike.dto.UserLikeCountDTO;
import com.ziyucoding.springboot.labs.redislike.dto.UserLikesDTO;
import com.ziyucoding.springboot.labs.redislike.mapper.UserLikesMapper;
import com.ziyucoding.springboot.labs.redislike.mapper.ViewItemMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.n3r.idworker.Sid;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ziyucoding.springboot.labs.redislike.service.DBLikeService;
import com.ziyucoding.springboot.labs.redislike.service.RedisLikeService;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * DB 点赞服务 实现类
 *
 * @author ziyucoding
 * @date 2023-02-07
 **/
@Service("dbLikeService")
@Slf4j
public class DBLikeServiceImpl implements DBLikeService {

    /**
     * Id生成器，利用idWorker产生唯一（不重复）自增式的id，可以根据需求选用其他方式
     */
    @Autowired
    private Sid sid;

    @Autowired
    private RedisLikeService redisLikeService;

    @Autowired
    private UserLikesMapper userLikesMapper;

    @Autowired
    private ViewItemMapper viewItemMapper;

    @Override
    public Boolean save(UserLikes userLike) {
        int rows = userLikesMapper.insert(userLike);
        return rows > 0;
    }

    @Override
    public Boolean update(UserLikes userLike) {
        UpdateWrapper<UserLikes> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", userLike.getId());
        updateWrapper.set("status", userLike.getStatus());
        updateWrapper.set("update_time", userLike.getUpdateTime());
        int rows = userLikesMapper.update(userLike, updateWrapper);
        return rows > 0;
    }

    @Override
    public Page<UserLikes> getLikedListByInfoId(String infoId, int pageNum, int pageSize) {
        // 分页获取列表
        Page<UserLikes> result = new Page<>();
        result.setCurrent(pageNum);
        result.setSize(pageSize);

        // 获取内容的id查询点赞列表
        QueryWrapper<UserLikes> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("info_id", infoId);
        result = userLikesMapper.selectPage(result, queryWrapper);
        return result;
    }

    @Override
    public Page<UserLikes> getLikedListByLikeUserId(String likeUserId, int pageNum, int pageSize) {
        // 分页获取列表
        Page<UserLikes> result = new Page<>();
        result.setCurrent(pageNum);
        result.setSize(pageSize);

        // 获取用户的id查询点赞列表
        QueryWrapper<UserLikes> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("like_user_id", likeUserId);
        result = userLikesMapper.selectPage(result, queryWrapper);
        return result;
    }

    @Override
    public UserLikes getByInfoIdAndLikeUserId(String infoId, String likeUserId) {
        Map<String, Object> itemMap = new HashMap<>();
        itemMap.put("info_id", infoId);
        itemMap.put("like_user_id", likeUserId);

        UserLikes userLikes = null;
        List<UserLikes> userLikesList = userLikesMapper.selectByMap(itemMap);
        if (CollectionUtils.isNotEmpty(userLikesList)) {
            userLikes = userLikesList.get(0);
        }
        return userLikes;
    }

    @Override
    public void transLikedFromRedis2DB() {
        // 批量获取缓存中的点赞数据
        List<UserLikesDTO> userLikesDTOList = redisLikeService.getLikedDataFromRedis();
        if (!CollectionUtils.isNotEmpty(userLikesDTOList)) {
            return;
        }

        for (UserLikesDTO item : userLikesDTOList) {
            String infoId = item.getInfoId();
            String likeUserId = item.getLikeUserId();
            UserLikes userLikes = getByInfoIdAndLikeUserId(infoId, likeUserId);
            if (userLikes == null) {
                // 无记录，新增
                UserLikes userLikesItem = userLikesDTOtoUserLikes(item);
                Boolean result = save(userLikesItem);
                if (!result) {
                    log.error("新增点赞数据失败！");
                    return;
                }
            } else {
                // 有记录，更新
                // 判断数据库中点赞状态与缓存中点赞状态一致性
                if (userLikes.getStatus() == item.getStatus()) { // 一致，无需持久化，点赞数量-1
                    redisLikeService.inDecrementLikedCount(item.getInfoId(), -1);
                } else {
                    // 不一致
                    if (userLikes.getStatus() == Constant.LikedStatusEum.LIKE.getCode()) {
                        // 在数据库中已经是点赞，则取消点赞，同时记得redis中的count-1
                        // 之前是点赞，现在改为取消点赞 1.设置更改status 2. redis中的count要-1（消除在数据库中自己的记录）
                        userLikes.setStatus(Constant.LikedStatusEum.UNLIKE.getCode());
                        redisLikeService.inDecrementLikedCount(item.getInfoId(), -1);
                    } else if (userLikes.getStatus() == Constant.LikedStatusEum.UNLIKE.getCode()) {
                        // 未点赞，则点赞，修改点赞状态和点赞数据+1
                        userLikes.setStatus(Constant.LikedStatusEum.LIKE.getCode());
                        redisLikeService.inDecrementLikedCount(item.getInfoId(), 1);
                    }
                    userLikes.setUpdateTime(LocalDateTime.now());
                    if (!update(userLikes)) {
                        // 更新点赞数据
                        log.info("更新点赞数据失败！");
                        return;
                    }
                }
            }
        }


    }

    @Override
    public void transLikedCountFromRedis2DB() {
        // 获取缓存中内容的点赞数列表
        List<UserLikeCountDTO> userLikeCountDTOList = redisLikeService.getLikedCountFromRedis();
        if (!CollectionUtils.isNotEmpty(userLikeCountDTOList)) {
            return;
        }

        for (UserLikeCountDTO item : userLikeCountDTOList) {
            ViewItem viewItem = viewItemMapper.selectById(item.getInfoId());
            if (viewItem != null) {
                // 新增点赞数
                Integer likeCount = viewItem.getLikeCount() + item.getLikeCount();
                viewItem.setLikeCount(likeCount);

                UpdateWrapper<ViewItem> updateWrapper = new UpdateWrapper<>();
                updateWrapper.set("like_count", viewItem.getLikeCount());
                updateWrapper.eq("id", viewItem.getId());
                int rows = viewItemMapper.update(viewItem, updateWrapper);
                if (rows <= 0) {
                    log.info("同步点赞数目数据异常，内容id为：" + item.getInfoId());
                }
            }
        }
    }

    /**
     * 转换
     *
     * @param userLikesDTO
     * @return UserLikes
     */
    private UserLikes userLikesDTOtoUserLikes(UserLikesDTO userLikesDTO) {
        UserLikes userLikes = new UserLikes();
        userLikes.setId(sid.nextShort());
        BeanUtils.copyProperties(userLikesDTO, userLikes);
        userLikes.setCreateTime(LocalDateTime.now());
        userLikes.setUpdateTime(LocalDateTime.now());
        return userLikes;
    }

}
